package com.dataseek.iot.device.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.dataseek.iot.device.entity.DayLevel;
import com.dataseek.iot.device.entity.DayUse;
import com.dataseek.iot.device.entity.DayUseDto;
import com.dataseek.iot.device.entity.LiquidJar;
import com.dataseek.iot.device.mapper.DayUseMapper;
import com.dataseek.iot.device.mapper.LiquidJarMapper;
import com.dataseek.iot.device.service.DayUseService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collector;
import java.util.stream.Collectors;

@Service
@Slf4j
public class DayUseServiceImpl extends ServiceImpl<DayUseMapper, DayUse> implements DayUseService {
    @Autowired
    LiquidJarMapper liquidJarMapper;

    @Override
    public List<DayUse> queryMonth(String jarCode, String deviceCode) {

        QueryWrapper<DayUse> qw = new QueryWrapper<>();
        if (jarCode != null && !jarCode.isEmpty()) {
            qw.eq("jar_code", jarCode);
        }

        if (deviceCode != null && !deviceCode.isEmpty()) {
            qw.eq("device_code", deviceCode);
        }

        qw.ge("create_time", this.getFirstDayOfMonth());
        qw.orderByAsc("create_time");
        return this.list(qw);
    }

    @Override
    public List<DayUse> queryYear(String jarCode, String deviceCode) {

        QueryWrapper<DayUse> qw = new QueryWrapper<>();
        if (jarCode != null && !jarCode.isEmpty()) {
            qw.eq("jar_code", jarCode);
        }

        if (deviceCode != null && !deviceCode.isEmpty()) {
            qw.eq("device_code", deviceCode);
        }

        qw.ge("create_time", this.getFirstDayOfYear());
        qw.orderByAsc("create_time");
        return this.list(qw);
    }

    //获取每月第一天
    private Date getFirstDayOfMonth() {
        Calendar calendar = Calendar.getInstance();
        calendar.set(Calendar.DAY_OF_MONTH, 1);
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);
        return  calendar.getTime();
    }

    //获取每年第一天
    private Date getFirstDayOfYear() {
        Calendar calendar = Calendar.getInstance();
        calendar.set(Calendar.DAY_OF_YEAR, 1);
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);
        return  calendar.getTime();
    }

    //获取昨天零点
    private Date getYesterday() {
        Calendar calendar = Calendar.getInstance();
        calendar.add(Calendar.DATE, -1);
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);
        return  calendar.getTime();
    }

    private Date getFirstDayOfWeek() {
        Calendar calendar = Calendar.getInstance();
        calendar.setFirstDayOfWeek(Calendar.MONDAY); //以周一为首日
        calendar.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY);
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);
        return  calendar.getTime();
    }

    private Date getLastWeek() {
        Calendar calendar = Calendar.getInstance();
        calendar.add(Calendar.DATE, -7);
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);
        return  calendar.getTime();
    }

    @Override
    public BigDecimal qryDashboardDay() {
        QueryWrapper<DayUse> qw = new QueryWrapper<>();
        qw.ge("create_time", this.getYesterday());
        return new BigDecimal(this.list(qw).stream().mapToDouble(p->p.getUsedAmountVol().doubleValue()).average().getAsDouble())
                .setScale(2,BigDecimal.ROUND_HALF_UP);
    }

    @Override
    public List<DayUse> qryDashboardWeek() {
        QueryWrapper<DayUse> qw = new QueryWrapper<>();
        qw.ge("create_time", this.getFirstDayOfWeek());
        List<DayUse> useList = this.list(qw);
        Map<String, List<DayUse>> useMap = useList.stream().collect(Collectors.groupingBy(DayUse::getCalDate));
        List<DayUse> reList = new ArrayList<>();
        for (Map.Entry<String, List<DayUse>> en : useMap.entrySet()) {
            DayUse reDto = new DayUse();
            reDto.setCalDate(en.getKey());
            reDto.setUsedAmountVol(new BigDecimal(en.getValue().stream().mapToDouble(p->p.getUsedAmountVol().doubleValue()).average().getAsDouble())
                    .setScale(2,BigDecimal.ROUND_HALF_UP));
            reList.add(reDto);
        }
        reList = reList.stream().sorted(Comparator.comparing(DayUse::getCalDate)).collect(Collectors.toList());
        return reList;
    }

    @Override
    public List<DayUse> qryDashboardMonth() {
        QueryWrapper<DayUse> qw = new QueryWrapper<>();
        qw.ge("create_time", this.getFirstDayOfMonth());
        List<DayUse> useList = this.list(qw);
        Map<String, List<DayUse>> useMap = useList.stream().collect(Collectors.groupingBy(DayUse::getCalDate));
        List<DayUse> reList = new ArrayList<>();
        for (Map.Entry<String, List<DayUse>> en : useMap.entrySet()) {
            DayUse reDto = new DayUse();
            reDto.setCalDate(en.getKey());
            reDto.setUsedAmountVol(new BigDecimal(en.getValue().stream().mapToDouble(p->p.getUsedAmountVol().doubleValue()).average().getAsDouble())
                    .setScale(2,BigDecimal.ROUND_HALF_UP));
            reList.add(reDto);
        }
        reList = reList.stream().sorted(Comparator.comparing(DayUse::getCalDate)).collect(Collectors.toList());
        return reList;
    }

    @Override
    public List<DayUse> qryDashboardYear() {
        QueryWrapper<DayUse> qw = new QueryWrapper<>();
        qw.ge("create_time", this.getFirstDayOfYear());
        List<DayUse> useList = this.list(qw);
        Map<String, List<DayUse>> useMap = useList.stream().collect(Collectors.groupingBy(DayUse::getCalDate));
        List<DayUse> reList = new ArrayList<>();
        for (Map.Entry<String, List<DayUse>> en : useMap.entrySet()) {
            DayUse reDto = new DayUse();
            reDto.setCalDate(en.getKey());
            reDto.setUsedAmountVol(new BigDecimal(en.getValue().stream().mapToDouble(p->p.getUsedAmountVol().doubleValue()).average().getAsDouble())
                    .setScale(2,BigDecimal.ROUND_HALF_UP));
            reList.add(reDto);
        }
        reList = reList.stream().sorted(Comparator.comparing(DayUse::getCalDate)).collect(Collectors.toList());
        return reList;
    }

    @Override
    public List<DayUseDto> qryDashboardWeekWithJar() {
        QueryWrapper<DayUse> qw = new QueryWrapper<>();
        //往前数7天
        qw.ge("create_time", this.getLastWeek());
        List<DayUse> useList = this.list(qw);
        Map<String, List<DayUse>> useMap = useList.stream().collect(Collectors.groupingBy(DayUse::getJarCode));
        List<DayUseDto> reList = new ArrayList<>();
        for (Map.Entry<String, List<DayUse>> en : useMap.entrySet()) {
            QueryWrapper<LiquidJar> qwJar = new QueryWrapper<>();
            qwJar.eq("jar_code", en.getKey());
            LiquidJar jarDto = liquidJarMapper.selectOne(qwJar);
            if (jarDto != null) {
                DayUseDto reDto = new DayUseDto();
                reDto.setJarName(jarDto.getJarName());
                reDto.setDayUseList(en.getValue().stream().sorted(Comparator.comparing(DayUse::getCalDate)).collect(Collectors.toList()));
                reList.add(reDto);
            }
        }
        return reList;
    }


}
